# coding: UTF-8
# @Date    ：2024/10/14 18:01 
# @File    : db_config.py
# :Author:  fum
from typing import Any
from urllib.parse import quote_plus

from pydantic import Field, computed_field
from pydantic_settings import BaseSettings


class DatabaseConfigSettings(BaseSettings):
    """数据库配置"""
    DB_HOST: str = Field(
        description="db host 当多个服务（容器）被定义在同一个 Docker Compose 文件中，并且它们被配置为加入同一个网络时，Docker 会自动为每个服务创建一个 DNS 条目。这个 DNS 条目将服务名称解析为该服务的内部 IP 地址。",
        default="mysql",
    )

    DB_PORT: int = Field(
        description="db port",
        default=3306,
    )

    DB_USERNAME: str = Field(
        description="db username",
        default="root",
    )

    DB_PASSWORD: str = Field(
        description="db password",
        default="123456",
    )

    DB_DATABASE: str = Field(
        description="db database",
        default="admin",
    )

    DB_CHARSET: str = Field(
        description="db charset",
        default="utf8mb4",
    )

    DB_EXTRAS: str = Field(
        description="db extras options. Example: keepalives_idle=60&keepalives=1",
        default="",
    )

    SQLALCHEMY_DATABASE_URI_SCHEME: str = Field(
        description="db uri scheme",
        default="mysql+pymysql",
    )

    @computed_field
    @property
    def SQLALCHEMY_DATABASE_URI(self) -> str:
        """sqlalchemy database url"""
        db_extras = (
            f"{self.DB_EXTRAS}&charset={self.DB_CHARSET}" if self.DB_CHARSET else self.DB_EXTRAS
        ).strip("&")
        db_extras = f"?{db_extras}" if db_extras else ""
        return (
            f"{self.SQLALCHEMY_DATABASE_URI_SCHEME}://"
            f"{quote_plus(self.DB_USERNAME)}:{quote_plus(self.DB_PASSWORD)}@"
            f"{self.DB_HOST}:{self.DB_PORT}/{self.DB_DATABASE}"
            f"{db_extras}"
        )

    SQLALCHEMY_POOL_SIZE: int = Field(
        description="pool size of SqlAlchemy",
        default=30,
    )

    SQLALCHEMY_MAX_OVERFLOW: int = Field(
        description="max overflows for SqlAlchemy",
        default=10,
    )

    SQLALCHEMY_POOL_RECYCLE: int = Field(
        description="SqlAlchemy pool recycle",
        default=3600,
    )

    SQLALCHEMY_POOL_PRE_PING: bool = Field(
        description="whether to enable pool pre-ping in SqlAlchemy",
        default=True,
    )

    SQLALCHEMY_ECHO: bool | str = Field(
        description="whether to enable SqlAlchemy echo",
        default=False,
    )

    @computed_field
    @property
    def SQLALCHEMY_ENGINE_OPTIONS(self) -> dict[str, Any]:
        """sqlalchemy engine options"""
        return {
            "pool_size": self.SQLALCHEMY_POOL_SIZE,
            "max_overflow": self.SQLALCHEMY_MAX_OVERFLOW,
            "pool_recycle": self.SQLALCHEMY_POOL_RECYCLE,
            "pool_pre_ping": self.SQLALCHEMY_POOL_PRE_PING,
            "connect_args": {"charset": self.DB_CHARSET},
        }
